/*
 * ELF executable loading
 * Copyright (c) 2003, Jeffrey K. Hollingsworth <hollings@cs.umd.edu>
 * Copyright (c) 2003, David H. Hovemeyer <daveho@cs.umd.edu>
 * $Revision: 1.29 $
 * 
 * This is free software.  You are permitted to use,
 * redistribute, and modify it as specified in the file "COPYING".
 */

#include <geekos/errno.h>
#include <geekos/kassert.h>
#include <geekos/ktypes.h>
#include <geekos/screen.h>  /* for debug Print() statements */
#include <geekos/pfat.h>
#include <geekos/malloc.h>
#include <geekos/string.h>
#include <geekos/elf.h>


/**
 * From the data of an ELF executable, determine how its segments
 * need to be loaded into memory.
 * @param exeFileData buffer containing the executable file
 * @param exeFileLength length of the executable file in bytes
 * @param exeFormat structure describing the executable's segments
 *   and entry address; to be filled in
 * @return 0 if successful, < 0 on error
 */
int Parse_ELF_Executable(char *exeFileData, ulong_t exeFileLength,
    struct Exe_Format *exeFormat)
{
	elfHeader *ehdr = NULL;
	programHeader *phdr = NULL;
	int i = 0;

	/* obtenemos el ELF HEADER */
	ehdr = (elfHeader *) exeFileData;
	

	/** VERIFICACIÓN DE QUE SEA UN ARCHIVO VÁLIDO **/
	/* identificación de un ELF: los primeros 4 bytes deben ser 0x7f y "ELF" */
	if(strncmp(exeFileData, "\x7f""ELF", 4))
	{
		Print("El archivo no es un ELF valido\n");
		return ENOEXEC; /* definido en errno.h */
	}

	/* verificamos que no haya más segmentos de los permitidos */
	if( (ehdr->phnum) > EXE_MAX_SEGMENTS)
	{
		Print("El programa tiene %d segmentos y el maximo permitido es %d\n",
				ehdr->phnum, EXE_MAX_SEGMENTS);
		return ENOEXEC;
	}

	/** FIN VERIFICACIÓN DEL ARCHIVO **/
	/** COMENZAMOS A LLENAR LA ESTRUCUTRA Exe_Format **/
	exeFormat->numSegments = ehdr->phnum;
	exeFormat->entryAddr = ehdr->entry;

	/* obtenemos la PHT (program header table) */
	phdr = (programHeader *) (exeFileData + ehdr->phoff);
	for (i=0; i<ehdr->phnum; i++) /* debemos llenar cada segmento */
	{
		/* el segmento "actual" es (*exeFormat)->segmentList[i] */
		(exeFormat->segmentList[i]).offsetInFile = phdr[i].offset;
		(exeFormat->segmentList[i]).lengthInFile = phdr[i].fileSize;
		(exeFormat->segmentList[i]).startAddress = phdr[i].vaddr;
		(exeFormat->segmentList[i]).sizeInMemory = phdr[i].memSize;

		/* hay q ver q el tamaño del archivo no exceda el de la memoria */
		if (phdr[i].fileSize > phdr[i].memSize)
		{
			Print("Segmento %i:Tamaño de archivo excede el de memoria\n", i);
			return ENOEXEC;
		}
			
	}

	return 0;
	
}

